﻿using Microsoft.VisualBasic;
using Neo4j.Driver;
using Neo4JConnector.Semantic;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace Neo4JConnector.Core
{
    public class KnowledgeGraphClient
    {
        private readonly IDriver _driver;
        private readonly string _database;

        public KnowledgeGraphClient(
            string uri, string database, string user, string password)
        {
            _driver = GraphDatabase.Driver(uri, AuthTokens.Basic(user, password));
            _database = database;
        }

        // 在创建节点时动态创建索引
        private async Task EnsureIndexForLabelAsync(string label)
        {
            try
            {
                var constraintName = $"{label.ToLower()}_id_unique";
                var indexName = $"{label.ToLower()}_id_index";

                // 检查是否已有约束
                var hasConstraint = await CheckConstraintExistsAsync(constraintName);
                if (hasConstraint)
                {
                    Console.WriteLine($"Constraint already exists for label: {label}");
                    return;
                }

                // 检查是否已有普通索引
                var hasIndex = await CheckIndexExistsAsync(indexName, label);
                if (hasIndex)
                {
                    Console.WriteLine($"Index already exists for label: {label}");
                    return;
                }

                // 优先创建约束（包含索引功能）
                await ExecuteCypherAsync($"CREATE CONSTRAINT {constraintName} IF NOT EXISTS FOR (n:{label}) REQUIRE n.id IS UNIQUE");
                Console.WriteLine($"Constraint created for label: {label}");

            }
            catch (Exception ex)
            {
                Console.WriteLine($"Warning: Could not ensure index/constraint for {label}: {ex.Message}");
            }
        }

        private async Task<bool> CheckConstraintExistsAsync(string constraintName)
        {
            try
            {
                var result = await ExecuteCypherAsync($"SHOW CONSTRAINTS WHERE name = '{constraintName}'");
                return result != null; // 根据你的返回类型调整
            }
            catch
            {
                return false;
            }
        }

        private async Task<bool> CheckIndexExistsAsync(string indexName, string label)
        {
            try
            {
                var result = await ExecuteCypherAsync($"SHOW INDEXES WHERE name = '{indexName}' OR (labelsOrTypes = ['{label}'] AND properties = ['id'])");
                return result != null; // 根据你的返回类型调整
            }
            catch
            {
                return false;
            }
        }

        #region 实体管理

        public async Task<string> AddEntity(string label, Dictionary<string, object> properties, string? externalId = null)
        {
            await EnsureIndexForLabelAsync(label);

            var id = externalId ?? Guid.NewGuid().ToString();
            properties["id"] = id;

            await using var session = CreateSession();
            var result = await session.RunAsync(
                $"CREATE (n:{label} $props) RETURN n.id AS id",
                new { props = properties });

            var record = await result.SingleAsync();
            return record["id"].As<string>();
        }

        public async Task UpdateEntity(string label, string id, Dictionary<string, object> properties)
        {
            await using var session = CreateSession();

            // 确保不修改id
            var props = new Dictionary<string, object>(properties);
            props["id"] = id; // 保持id不变

            await session.RunAsync(
                $"MATCH (n:{label} {{id: $id}}) SET n = $props",
                new { id, props });
        }

        public async Task DeleteEntity(string label, string id)
        {
            await using var session = CreateSession();
            await session.RunAsync(
                $"MATCH (n:{label} {{id: $id}}) DETACH DELETE n",
                new { id });
        }

        #endregion

        #region 关系管理

        public async Task AddRelation(
            string label1, string id1,
            string label2, string id2,
            string relationType,
            Dictionary<string, object>? properties = null)
        {
            await using var session = CreateSession();

            // 确保属性字典不为null
            properties ??= new Dictionary<string, object>();

            // 如果属性中没有id，自动生成一个
            if (!properties.ContainsKey("id"))
            {
                properties["id"] = Guid.NewGuid().ToString();
            }

            await session.RunAsync(
                $"MATCH (a:{label1} {{id: $id1}}), (b:{label2} {{id: $id2}}) " +
                $"CREATE (a)-[r:{relationType} $props]->(b)",
                new
                {
                    id1,
                    id2,
                    props = properties
                });
        }

        public async Task RemoveRelation(
            string label1, string id1,
            string label2, string id2,
            string relationType)
        {
            await using var session = CreateSession();
            await session.RunAsync(
                $"MATCH (a:{label1} {{id: $id1}})-[r:{relationType}]->(b:{label2} {{id: $id2}}) " +
                "DELETE r",
                new { id1, id2 });
        }

        public async Task UpdateRelation(
            string label1, string id1,
            string label2, string id2,
            string relationType,
            Dictionary<string, object> properties)
        {
            await using var session = CreateSession();
            await session.RunAsync(
                $"MATCH (a:{label1} {{id: $id1}})-[r:{relationType}]->(b:{label2} {{id: $id2}}) " +
                "SET r += $props",
                new { id1, id2, props = properties });
        }

        #endregion

        #region 路径查询

        public async Task<List<Dictionary<string, object>>> QueryPath(
            string label,
            string id,
            PathDirection direction,
            List<QueryConditionObject>? filters = null,
            int maxDepth = 5)
        {
            await using var session = CreateSession();

            string matchPattern = direction switch
            {
                PathDirection.Outgoing => $"(start:{label} {{id: $id}})-[*1..{maxDepth}]->(node)",
                PathDirection.Incoming => $"(node)-[*1..{maxDepth}]->(end:{label} {{id: $id}})",
                PathDirection.Include => $"(start)-[*1..{maxDepth}]-(node) WHERE start.id = $id",
                _ => throw new ArgumentException("Invalid direction")
            };

            // 构建过滤条件和参数
            var (filterClause, parameters) = BuildComplexFilterClause(filters, "node");
            parameters["id"] = id;

            var query = $@"
                MATCH {matchPattern}
                {filterClause}
                RETURN DISTINCT node, labels(node) AS labels, properties(node) AS props";

            var result = await session.RunAsync(query, parameters);
            return await ProcessNodeResults(result);
        }

        public async Task<List<Dictionary<string, object>>> GetRelation(
            string label1, string id1,
            string label2, string id2,
            string relationType)
        {
            await using var session = CreateSession();

            var cursor = await session.RunAsync(
                $"MATCH (a:{label1} {{id: $id1}})-[rel:{relationType}]->(b:{label2} {{id: $id2}}) " +
                "RETURN rel, type(rel) AS type",
                new { id1, id2 });

            return await ProcessRelationResults(cursor);
        }


        #endregion

        #region 实体查询

        public async Task<Dictionary<string, object>> GetEntity(string label, string id)
        {
            var list = await QueryEntities(label, new EntityQueryOptions
            {
                Filters = new List<QueryConditionObject>
                {
                    new QueryConditionObject
                    {
                        Name = "id",
                        Op = Operation.匹配,
                        Value = id
                    }
                },
                Limit = 1
            });

            return list.FirstOrDefault() ?? null;
        }

        public async Task<List<string>> GetAllEntities(string label)
        {
            await using var session = CreateSession();

            // 构建过滤条件和参数

            var query = $@"
                MATCH (e:{label})
                RETURN id(e) AS id";

            var result = await session.RunAsync(query);

            return await ProcessNodeIdResults(result);
        }

        public async Task<List<Dictionary<string, object>>> QueryEntities(
            string label,
            EntityQueryOptions? options = null)
        {
            await using var session = CreateSession();

            options ??= new EntityQueryOptions();

            var (filterClause, parameters) = BuildComplexFilterClause(options.Filters, "e");

            // 构建排序子句
            string orderClause = "";
            if (!string.IsNullOrEmpty(options.OrderBy))
            {
                var direction = options.Ascending ? "ASC" : "DESC";
                orderClause = $"ORDER BY e.{options.OrderBy} {direction}";
            }

            // 构建分页子句
            string paginationClause = "";
            if (options.Skip > 0)
            {
                paginationClause = $"SKIP {options.Skip} LIMIT {options.Limit}";
            }
            else
            {
                paginationClause = $"LIMIT {options.Limit}";
            }

            var query = $@"
                MATCH (e:{label})
                {filterClause}
                RETURN properties(e) AS props
                {orderClause}
                {paginationClause}";

            var result = await session.RunAsync(query, parameters);
            return await ProcessPropertyResults(result);
        }

        #endregion

        #region 关系查询

        public async Task<List<Dictionary<string, object>>> QueryRelations(string label, string id, string? relationType = null, PathDirection direction = PathDirection.Outgoing, List<QueryConditionObject>? relationFilters = null, List<QueryConditionObject>? targetNodeFilters = null)
        {
            await using var session = CreateSession();

            string relationPattern = relationType != null
                ? $":{relationType}"
                : "";

            string directionPattern = direction switch
            {
                PathDirection.Outgoing => "->",
                PathDirection.Incoming => "<-",
                PathDirection.Include => "--",
                _ => "--"
            };

            // 构建关系属性过滤条件
            var (relationFilterClause, relationParams) = BuildComplexFilterClause(relationFilters, "r");

            // 构建目标节点属性过滤条件
            var (targetFilterClause, targetParams) = BuildComplexFilterClause(targetNodeFilters, "target");

            // 合并参数
            var parameters = new Dictionary<string, object> { ["id"] = id };
            foreach (var param in relationParams) parameters[param.Key] = param.Value;
            foreach (var param in targetParams) parameters[param.Key] = param.Value;

            // 构建完整查询
            var query = $@"
                MATCH (source:{label} {{id: $id}}){directionPattern}[r{relationPattern}]-(target)
                {relationFilterClause}
                {targetFilterClause}
                RETURN properties(r) AS relProps, properties(target) AS targetProps, type(r) AS relType";

            var result = await session.RunAsync(query, parameters);
            return await ProcessRelationResults(result);
        }

        #endregion

        #region 批量操作

        public async Task BulkAddEntities(string label, List<Dictionary<string, object>> entities, string? idField = null)
        {
            await using var session = CreateSession();

            // 预处理实体
            var processedEntities = new List<Dictionary<string, object>>();
            foreach (var entity in entities)
            {
                var processed = new Dictionary<string, object>(entity);

                // 处理ID字段
                if (idField != null && entity.ContainsKey(idField))
                {
                    processed["id"] = entity[idField];
                }
                else if (!entity.ContainsKey("id"))
                {
                    processed["id"] = Guid.NewGuid().ToString();
                }

                processedEntities.Add(processed);
            }

            // 批量添加
            var batchSize = 1000;
            for (int i = 0; i < processedEntities.Count; i += batchSize)
            {
                var batch = processedEntities.Skip(i).Take(batchSize).ToList();
                await session.RunAsync(
                    $"UNWIND $batch AS entity CREATE (n:{label}) SET n = entity",
                    new { batch });
            }
        }

        public async Task BulkAddRelations(List<RelationData> relations)
        {
            await using var session = CreateSession();

            var batchSize = 1000;
            for (int i = 0; i < relations.Count; i += batchSize)
            {
                var batch = relations.Skip(i).Take(batchSize).ToList();

                // 为每个关系生成唯一的ID（如果未提供）
                var processedBatch = batch.Select(r => new
                {
                    id1 = r.Id1,
                    id2 = r.Id2,
                    type = r.Type,
                    props = EnsureRelationProperties(r.Properties)
                }).ToList();

                await session.RunAsync(
                    "UNWIND $batch AS rel " +
                    "MATCH (a {id: rel.id1}), (b {id: rel.id2}) " +
                    $"CREATE (a)-[r:{relations[0].Type}]->(b) " +
                    "SET r = rel.props",
                    new { batch = processedBatch });
            }
        }

        #endregion

        #region 图算法
        // 推荐保留这个版本 - 兼容性最好，性能稳定
        public async Task<Dictionary<string, object>> ShortestPath(
            string label1, string id1,
            string label2, string id2,
            string relationType,
            string? weightProperty = null,
            float defaultWeight = 1.0f,
            int maxHops = 6)
        {
            await using var session = CreateSession();

            string cypherQuery;
            var parameters = new Dictionary<string, object>
            {
                ["id1"] = id1,
                ["id2"] = id2,
                ["defaultWeight"] = defaultWeight
            };

            if (string.IsNullOrEmpty(weightProperty))
            {
                // 无权重的最短路径（按跳数）- 最高效
                cypherQuery = $@"
            MATCH (start:{label1} {{id: $id1}}), (end:{label2} {{id: $id2}})
            MATCH path = shortestPath((start)-[:{relationType}*1..{maxHops}]-(end))
            RETURN 
                nodes(path) AS nodes,
                relationships(path) AS relationships,
                length(path) AS pathLength,
                toFloat(length(path)) AS totalWeight
            LIMIT 1";
            }
            else
            {
                // 带权重的最短路径 - 社区版兼容版本
                cypherQuery = $@"
            MATCH (start:{label1} {{id: $id1}}), (end:{label2} {{id: $id2}})
            
            // 查找所有可能的路径
            MATCH paths = (start)-[:{relationType}*1..{maxHops}]-(end)
            
            // 计算路径权重，使用兼容性最好的类型检查方式
            WITH paths, 
            [r IN relationships(paths) | 
                CASE 
                    WHEN r.{weightProperty} IS NULL THEN $defaultWeight
                    // 检查是否为数值类型（最兼容的方式）
                    WHEN r.{weightProperty} + 0 = r.{weightProperty} THEN toFloat(r.{weightProperty})
                    // 尝试字符串转数值
                    WHEN toString(r.{weightProperty}) =~ '^[+-]?[0-9]*\\.?[0-9]+([eE][+-]?[0-9]+)?$'
                    THEN toFloat(toString(r.{weightProperty}))
                    ELSE $defaultWeight
                END
            ] as weights,
            length(paths) as pathLength
            
            WITH paths, weights, pathLength,
                 reduce(sum = 0.0, weight IN weights | sum + weight) as totalWeight
            
            // 按权重排序，权重相同时按路径长度排序
            ORDER BY totalWeight ASC, pathLength ASC
            LIMIT 1
            
            RETURN 
                nodes(paths) AS nodes,
                relationships(paths) AS relationships,
                pathLength AS pathLength,
                totalWeight AS totalWeight";
            }

            var result = await session.RunAsync(cypherQuery, parameters);
            return await ProcessShortestPathResults(result);
        }

        public async Task<List<Dictionary<string, object>>> CommunityDetection()
        {
            await using var session = CreateSession();
            var result = await session.RunAsync(
                "CALL gds.louvain.stream({ " +
                "  nodeQuery: 'MATCH (n) RETURN id(n) AS id', " +
                "  relationshipQuery: 'MATCH (a)-[r]-(b) RETURN id(a) AS source, id(b) AS target' " +
                "}) YIELD nodeId, communityId " +
                "RETURN communityId, COUNT(nodeId) AS size");

            return await ProcessCommunityResults(result);
        }

        #endregion

        #region 底层Cypher执行

        private IAsyncSession CreateSession()
        {
            return _driver.AsyncSession(o => o.WithDatabase(_database));
        }

        public async Task<CypherResult> ExecuteCypherAsync(
            string cypherQuery,
            Dictionary<string, object>? parameters = null,
            CancellationToken cancellationToken = default)
        {
            var stopwatch = Stopwatch.StartNew();

            await using var session = CreateSession();
            var result = await session.RunAsync(cypherQuery, parameters ?? new Dictionary<string, object>());

            var records = new List<CypherRecord>();
            while (await result.FetchAsync())
            {
                var record = new CypherRecord(
                    Values: result.Current.Values.ToDictionary(
                        kvp => kvp.Key,
                        kvp => ConvertValue(kvp.Value)),
                    Keys: result.Current.Keys.ToList()
                );
                records.Add(record);
            }

            var summary = await result.ConsumeAsync();

            stopwatch.Stop();

            return new CypherResult(
                Records: records,
                Summary: new Dictionary<string, object>
                {
                    ["queryType"] = summary.QueryType,
                    ["counters"] = summary.Counters,
                    ["database"] = summary.Database,
                    ["resultAvailableAfter"] = summary.ResultAvailableAfter,
                    ["resultConsumedAfter"] = summary.ResultConsumedAfter
                },
                ExecutionTime: stopwatch.Elapsed,
                NodesCreated: summary.Counters.NodesCreated,
                NodesDeleted: summary.Counters.NodesDeleted,
                RelationshipsCreated: summary.Counters.RelationshipsCreated,
                RelationshipsDeleted: summary.Counters.RelationshipsDeleted,
                PropertiesSet: summary.Counters.PropertiesSet
            );
        }

        public async Task<IAsyncEnumerable<CypherRecord>> ExecuteCypherStreamAsync(
            string cypherQuery,
            Dictionary<string, object>? parameters = null,
            CancellationToken cancellationToken = default)
        {
            await using var session = CreateSession();
            var result = await session.RunAsync(cypherQuery, parameters ?? new Dictionary<string, object>());

            return StreamRecordsAsync(result);
        }

        #endregion

        #region 事务支持

        public async Task<ITransaction> BeginTransactionAsync()
        {
            var session = CreateSession();
            var transaction = await session.BeginTransactionAsync();
            return new Neo4jTransaction(session, transaction);
        }

        public async Task CommitTransactionAsync(ITransaction transaction)
        {
            if (transaction is Neo4jTransaction neo4jTransaction)
            {
                await neo4jTransaction.CommitAsync();
            }
        }

        public async Task RollbackTransactionAsync(ITransaction transaction)
        {
            if (transaction is Neo4jTransaction neo4jTransaction)
            {
                await neo4jTransaction.RollbackAsync();
            }
        }

        #endregion

        #region 工具方法

        public async Task<Dictionary<string, object>> GetRelationProperties(
            string label1, string id1,
            string label2, string id2,
            string relationType)
        {
            await using var session = CreateSession();

            var result = await session.RunAsync(
                $"MATCH (a:{label1} {{id: $id1}})-[r:{relationType}]->(b:{label2} {{id: $id2}}) " +
                "RETURN properties(r) AS props",
                new { id1, id2 });

            if (await result.FetchAsync())
            {
                return result.Current["props"].As<Dictionary<string, object>>();
            }

            return new Dictionary<string, object>();
        }

        public async Task<bool> RelationExists(
            string label1, string id1,
            string label2, string id2,
            string relationType)
        {
            await using var session = CreateSession();

            var result = await session.RunAsync(
                $"MATCH (a:{label1} {{id: $id1}})-[r:{relationType}]->(b:{label2} {{id: $id2}}) " +
                "RETURN count(r) > 0 AS exists",
                new { id1, id2 });

            if (await result.FetchAsync())
            {
                return result.Current["exists"].As<bool>();
            }

            return false;
        }

        public async Task MergeRelation(
            string label1, string id1,
            string label2, string id2,
            string relationType,
            Dictionary<string, object>? properties = null)
        {
            await using var session = CreateSession();

            properties ??= new Dictionary<string, object>();

            // 确保关系有ID
            if (!properties.ContainsKey("id"))
            {
                properties["id"] = Guid.NewGuid().ToString();
            }

            await session.RunAsync(
                $"MATCH (a:{label1} {{id: $id1}}), (b:{label2} {{id: $id2}}) " +
                $"MERGE (a)-[r:{relationType}]->(b) " +
                "SET r = $props",
                new { id1, id2, props = properties });
        }

        #endregion

        #region 辅助方法

        private async Task<Dictionary<string, object>> ProcessShortestPathResults(IResultCursor result)
        {
            var results = new List<Dictionary<string, object>>();

            if (await result.FetchAsync())
            {
                var nodes = result.Current["nodes"].As<List<INode>>()
                    .Select(n => new Dictionary<string, object>(n.Properties)
                    {
                        ["id"] = n.Properties.TryGetValue("id", out var id) ? id : null,
                        ["labels"] = n.Labels.ToList(),
                        ["properties"] = new Dictionary<string, object>(n.Properties)
                    })
                    .ToList();

                var relationships = result.Current["relationships"].As<List<IRelationship>>()
                    .Select(r => new Dictionary<string, object>
                    {
                        ["type"] = r.Type,
                        ["properties"] = new Dictionary<string, object>(r.Properties)
                    })
                    .ToList();

                var pathLength = result.Current["pathLength"].As<int>();
                var totalWeight = result.Current["totalWeight"].As<double>();

                return new Dictionary<string, object>
                {
                    ["nodes"] = nodes,
                    ["relationships"] = relationships,
                    ["pathLength"] = pathLength,
                    ["totalWeight"] = totalWeight,
                    ["path"] = new Dictionary<string, object>
                    {
                        ["start"] = nodes.FirstOrDefault(),
                        ["end"] = nodes.LastOrDefault(),
                        ["hops"] = pathLength,
                        ["weight"] = totalWeight
                    }
                };
            }

            return null;
        }


        private (string, Dictionary<string, object>) BuildComplexFilterClause(List<QueryConditionObject>? filters, string alias)
        {
            if (filters == null || filters.Count == 0)
                return ("", new Dictionary<string, object>());

            var conditions = new List<string>();
            var parameters = new Dictionary<string, object>();
            int paramIndex = 0;

            foreach (var filter in filters)
            {
                if (filter.Value == null)
                    continue;

                string paramName = $"{alias}_{filter.Name}_{paramIndex++}";
                string condition = BuildSingleCondition(alias, filter, paramName);

                if (!string.IsNullOrEmpty(condition))
                {
                    conditions.Add(condition);
                    parameters[paramName] = filter.Value;
                }
            }

            if (conditions.Count == 0)
                return ("", new Dictionary<string, object>());

            return ($"WHERE {string.Join(" AND ", conditions)}", parameters);
        }

        private string BuildSingleCondition(string alias, QueryConditionObject filter, string paramName)
        {
            return filter.Op switch
            {
                Operation.匹配 => $"{alias}.{filter.Name} = ${paramName}",
                Operation.不匹配 => $"{alias}.{filter.Name} <> ${paramName}",
                Operation.在里面 => $"{alias}.{filter.Name} IN ${paramName}",
                Operation.不在里面 => $"NOT {alias}.{filter.Name} IN ${paramName}",
                Operation.数值大于 => $"{alias}.{filter.Name} > ${paramName}",
                Operation.数值不大于 => $"{alias}.{filter.Name} <= ${paramName}",
                Operation.数值小于 => $"{alias}.{filter.Name} < ${paramName}",
                Operation.数值不小于 => $"{alias}.{filter.Name} >= ${paramName}",
                _ => string.Empty
            };
        }

        private string BuildFilterClause(Dictionary<string, object>? filters, string alias)
        {
            if (filters == null || filters.Count == 0)
                return "";

            var conditions = filters.Select((kvp, i) =>
                $"{alias}.{kvp.Key} = ${alias}_{kvp.Key}_{i}");

            return "WHERE " + string.Join(" AND ", conditions);
        }

        private Dictionary<string, object> BuildFilterParameters(Dictionary<string, object>? filters)
        {
            if (filters == null || filters.Count == 0)
                return new Dictionary<string, object>();

            var parameters = new Dictionary<string, object>();
            int i = 0;
            foreach (var kvp in filters)
            {
                parameters[$"node_{kvp.Key}_{i++}"] = kvp.Value;
            }
            return parameters;
        }

        private Dictionary<string, object> EnsureRelationProperties(Dictionary<string, object>? properties)
        {
            properties ??= new Dictionary<string, object>();

            // 确保关系有唯一的ID
            if (!properties.ContainsKey("id"))
            {
                properties["id"] = Guid.NewGuid().ToString();
            }

            return properties;
        }

        private async Task<List<Dictionary<string, object>>> ProcessNodeResults(IResultCursor result)
        {
            if (result == null) return [];

            var results = new List<Dictionary<string, object>>();
            while (await result.FetchAsync())
            {
                var node = result.Current["node"].As<INode>();
                var labels = result.Current["labels"].As<List<string>>();

                var resultDict = new Dictionary<string, object>
                {
                    ["id"] = node.Properties.TryGetValue("id", out var id) ? id : null,
                    ["labels"] = labels,
                    ["properties"] = new Dictionary<string, object>(node.Properties), // 添加Properties字段
                };

                // 保持向后兼容：将属性展平到根级别
                foreach (var prop in node.Properties)
                {
                    if (!resultDict.ContainsKey(prop.Key))
                    {
                        resultDict[prop.Key] = prop.Value;
                    }
                }

                results.Add(resultDict);
            }
            return results;
        }

        private async Task<List<string>> ProcessNodeIdResults(IResultCursor result)
        {
            if (result == null) return [];

            var results = new List<string>();
            while (await result.FetchAsync())
            {
                var node = result.Current;
                var id = node["id"];
                if (id != null)
                {
                    results.Add(id.ToString());
                }

            }
            return results;
        }


        private async Task<List<Dictionary<string, object>>> ProcessPropertyResults(IResultCursor result)
        {
            if (result == null) return [];

            var results = new List<Dictionary<string, object>>();
            while (await result.FetchAsync())
            {
                results.Add(result.Current["props"].As<Dictionary<string, object>>());
            }
            return results;
        }

        private async Task<List<Dictionary<string, object>>> ProcessRelationResults(IResultCursor result)
        {
            if (result == null) return [];

            var results = new List<Dictionary<string, object>>();
            while (await result.FetchAsync())
            {
                var relProps = result.Current["relProps"].As<Dictionary<string, object>>();
                var targetProps = result.Current["targetProps"].As<Dictionary<string, object>>();
                var relType = result.Current["relType"].As<string>();

                results.Add(new Dictionary<string, object>
                {
                    ["edgeProperties"] = relProps,
                    ["type"] = relType,
                    ["targetNodeProperties"] = targetProps
                });
            }
            return results;
        }

        private async Task<List<Dictionary<string, object>>> ProcessPathResults(IResultCursor result)
        {
            if (result == null) return [];

            var results = new List<Dictionary<string, object>>();
            while (await result.FetchAsync())
            {
                var nodes = result.Current["nodes"].As<List<INode>>()
                    .Select(n => n.Properties)
                    .ToList();

                var rels = result.Current["rels"].As<List<IRelationship>>()
                .Select(r => new Dictionary<string, object>
                {
                    ["type"] = r.Type,
                    ["properties"] = r.Properties
                })
                .ToList();

                results.Add(new Dictionary<string, object>
                {
                    ["nodes"] = nodes,
                    ["relationships"] = rels
                });
            }
            return results;
        }

        private async Task<List<Dictionary<string, object>>> ProcessCommunityResults(IResultCursor result)
        {
            if (result == null) return [];

            var results = new List<Dictionary<string, object>>();
            while (await result.FetchAsync())
            {
                results.Add(new Dictionary<string, object>
                {
                    ["communityId"] = result.Current["communityId"],
                    ["size"] = result.Current["size"]
                });
            }
            return results;
        }

        private object ConvertValue(object value)
        {
            // 简化的类型转换，移除复杂的反射逻辑
            switch (value)
            {
                case INode node:
                    return new Dictionary<string, object>
                    {
                        ["id"] = node.Properties.TryGetValue("id", out var id) ? id.ToString() : null,
                        ["labels"] = node.Labels,
                        ["properties"] = node.Properties
                    };

                case IRelationship rel:
                    return new Dictionary<string, object>
                    {
                        ["id"] = rel.Properties.TryGetValue("id", out var id2) ? id2.ToString() : null,
                        ["type"] = rel.Type,
                        ["properties"] = rel.Properties
                    };

                case IPath path:
                    return new Dictionary<string, object>
                    {
                        ["nodes"] = path.Nodes.Select(n => ConvertValue(n)).ToList(),
                        ["relationships"] = path.Relationships.Select(r => ConvertValue(r)).ToList()
                    };

                default:
                    return value;
            }
        }

        private async IAsyncEnumerable<CypherRecord> StreamRecordsAsync(IResultCursor result)
        {
            while (await result.FetchAsync())
            {
                yield return new CypherRecord(
                    Values: result.Current.Values.ToDictionary(
                        kvp => kvp.Key,
                        kvp => ConvertValue(kvp.Value)),
                    Keys: result.Current.Keys.ToList()
                );
            }
        }

        #endregion

        #region 内部类

        private class Neo4jTransaction : ITransaction
        {
            private readonly IAsyncSession _session;
            private readonly IAsyncTransaction _transaction;
            private bool _disposed = false;

            public Neo4jTransaction(IAsyncSession session, IAsyncTransaction transaction)
            {
                _session = session;
                _transaction = transaction;
            }

            public async Task<CypherResult> ExecuteAsync(
            string cypherQuery,
            Dictionary<string, object>? parameters = null,
            CancellationToken cancellationToken = default)
            {
                var result = await _transaction.RunAsync(cypherQuery, parameters ?? new Dictionary<string, object>());

                var records = new List<CypherRecord>();
                while (await result.FetchAsync())
                {
                    var record = new CypherRecord(
                        Values: result.Current.Values.ToDictionary(
                            kvp => kvp.Key,
                            kvp => kvp.Value),
                        Keys: result.Current.Keys.ToList()
                    );
                    records.Add(record);
                }

                return new CypherResult(
                    Records: records,
                    Summary: new Dictionary<string, object>(),
                    ExecutionTime: TimeSpan.Zero,
                    NodesCreated: 0,
                    NodesDeleted: 0,
                    RelationshipsCreated: 0,
                    RelationshipsDeleted: 0,
                    PropertiesSet: 0
                );
            }

            public async Task CommitAsync()
            {
                await _transaction.CommitAsync();
                await _session.CloseAsync();
            }

            public async Task RollbackAsync()
            {
                await _transaction.RollbackAsync();
                await _session.CloseAsync();
            }

            public void Dispose()
            {
                if (!_disposed)
                {
                    _session?.Dispose();
                    _disposed = true;
                }
            }
        }

        #endregion

        public void Dispose()
        {
            _driver?.Dispose();
        }
    }
}
